﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Z1029.NoteEditor
{
    public class JudgementLine : MonoBehaviour
    {
        public float speed, alpha;
        public List<SpeedEvent> speeds;
        public List<Z1029.NoteGlobalView.ValueSet> moves;
        public List<Z1029.NoteGlobalView.ValueSet> rotates;
        public List<Z1029.NoteGlobalView.ValueSet> alphas;
        public float bpm;
        public SpriteRenderer lineShow;
        public float[] positionX;
        public List<Note> nearJudgeNotes;
        public GameObject beatline;
        public GameObject litBeatline;
        public Beatline[] beatlines;
        public Beatline[] litBeatlines;
        public Beatline[] beatlinesBelow;
        public Beatline[] litBeatlinesBelow;

        public GameObject trackLinePrefab;
        public GameObject trackLineParent;
        public GameObject[] tracklines = new GameObject[11];



        private void Start()
        {
            InitBeatlines();
            InitTrackLine();
        }

        private void Update()
        {
            UpdateSpeed();
            if (LevelController.instance.showBeatline)
                UpdateBeatline();
            if (LevelController.instance.showTrackLine)
                UpdateTrackLine();

            if (LevelController.instance.showTrackLine)
            {
                if (trackLineParent.activeSelf == false) trackLineParent.SetActive(true);
            }
            else if (trackLineParent.activeSelf == true) trackLineParent.SetActive(false);
        }

        public void InitTrackLine()
        {
            GameObject g = new GameObject("TrackLines");
            g.transform.parent = transform;
            trackLineParent = g;
            for(int i=0;i<11;i++)
            {
                GameObject gg = Instantiate(trackLinePrefab, g.transform);
                gg.transform.localPosition = new Vector3((i - 5)* 2f,0,0);
                tracklines[i] = gg;
            }
        }

        public void InitBeatlines()
        {
            beatlines = new Beatline[20];
            beatlinesBelow = new Beatline[20];
            for (int i = 0; i < 20; i++)
            {
                GameObject g = Instantiate(beatline, transform);
                Beatline b = g.GetComponent<Beatline>();
                beatlines[i] = b;
                b.index = i;
                b.Init(this);
            }
            for (int i = 0; i < 20; i++)
            {
                GameObject g = Instantiate(beatline, transform);
                Beatline b = g.GetComponent<Beatline>();
                beatlinesBelow[i] = b;
                b.below = true;
                b.index = i;
                b.Init(this);
            }
            litBeatlines = new Beatline[20 * 32];
            litBeatlinesBelow = new Beatline[20 * 32];
            for (int i = 0; i < 20; i++)
            {
                for (int j = 1; j < 32; j++)
                {
                    GameObject g = Instantiate(litBeatline, transform);
                    Beatline b = g.GetComponent<Beatline>();
                    litBeatlines[i * 32 + j] = b;
                    b.index = i;
                    b.onDensityIn = j;
                    b.Init(this);
                }
            }
            for (int i = 0; i < 20; i++)
            {
                for (int j = 1; j < 32; j++)
                {
                    GameObject g = Instantiate(litBeatline, transform);
                    Beatline b = g.GetComponent<Beatline>();
                    litBeatlinesBelow[i * 32 + j] = b;
                    b.below = true;
                    b.index = i;
                    b.onDensityIn = j;
                    b.Init(this);
                }
            }
        }

        public void UpdateBeatline()
        {
            for (int i = 0; i < 20; i++)
            {
                Beatline b = beatlines[i];
                b.index = i + 1 + Mathf.RoundToInt(LevelController.instance.NowBeatTime / LevelController.density);
            }
            for (int i = 0; i < 20; i++)
            {
                Beatline b = beatlinesBelow[i];
                b.index = i + 1 + Mathf.RoundToInt(LevelController.instance.NowBeatTime / LevelController.density);
            }

            for (int i = 0; i < 20; i++)
            {
                for (int j = 1; j < 32; j++)
                {
                    Beatline b = litBeatlines[i * 32 + j];
                    b.index = i + Mathf.RoundToInt(LevelController.instance.NowBeatTime / LevelController.density);
                }
            }
            for (int i = 0; i < 20; i++)
            {
                for (int j = 1; j < 32; j++)
                {
                    Beatline b = litBeatlinesBelow[i * 32 + j];
                    b.index = i + Mathf.RoundToInt(LevelController.instance.NowBeatTime / LevelController.density);
                }
            }
        }

        public void UpdateTrackLine()
        {
            for (int i = 0; i < 11; i++)
            {
                tracklines[i].transform.localPosition = new Vector3((i - 5) * LevelController.instance.tracklineDensity, 0, 0);
            }
        }

        public void UpdateSpeed()
        {
            speed = GetSpeed(LevelController.nowTime);
        }

        public float GetSpeed(double time)
        {
            for (int i = 0; i < speeds.Count; i++)
            {
                float? value = Utils.GetValueFromTimeAndValue(time, speeds[i].startTime, speeds[i].endTime, speeds[i].value, speeds[i].value);
                if (value != null)
                {
                    return (float)value;
                }
            }
            return 0;
        }

        public double GetSpeedDistance(double time)
        {
            //double num = 0;
            //int index = speeds.Count - 1;
            //for (int i = 0; i < speeds.Count; i++)
            //{
            //    float start = speeds[i].startTime;
            //    float end = speeds[i].endTime;
            //    float value = speeds[i].value;
            //    if (start > time)
            //    {
            //        index = i - 1;
            //        break;
            //    }
            //    if (end > LevelController.nowTime)
            //    {
            //        if (start < LevelController.nowTime)
            //            num += (end - LevelController.nowTime) * value;
            //        else num += (end - start) * value;
            //    }
            //}
            //num -= (speeds[index].endTime - time) * speeds[index].value;
            ////num /= 2;
            double num = (time - LevelController.nowTime) * 12; 
            return num;
        }

        public double DistanceToTime(float posY, bool below)
        {
            float y;
            double time = 0;
            double deltaT = Utils.GetTimeFromBeatTime(1, bpm);
            for (; ; )
            {
                y = (float)GetSpeedDistance(time);
                if (y >= posY && !below)
                    break;
                if (-y <= posY && below)
                    break;
                if (time > LevelController.instance.music.length)
                    break;
                time += deltaT;
            }
            return time;
        }

    }
}
